#include "ModuleCLUTSurveyColorLimits.h"

void ModuleCLUTSurveyColorLimits::init(QCVModuleHandlerInterface * parent)
{
	this->parent=parent;
	parent->setAutoProcess(false);
	win=new QWidget();
	
	pb_loadFuzzyCLUT=new QPushButton(tr("Load Fuzzy CLUT"),win);
	pb_saveResults=new QPushButton(tr("Save results"),win);
	pb_askMe=new QPushButton(tr("Get flop"),win);
	pb_clear=new QPushButton(tr("Clear results"),win);
	confiance_threshold=new QSpinBox(win);
	confiance_threshold->setPrefix(tr("confiance_threshold="));
	confiance_threshold->setSuffix(tr("%"));
	confiance_threshold->setRange(0,100);
	confiance_threshold->setValue(50);
	
	similarity_threshold=new QSpinBox(win);
	similarity_threshold->setPrefix(tr("similarity_threshold="));
	similarity_threshold->setSuffix(tr("%"));
	similarity_threshold->setRange(0,100);
	similarity_threshold->setValue(20);
	
	pbBarFlop=new QProgressBar(win);
	
	sb_nbColorsAsked=new QSpinBox(win);
	sb_nbColorsAsked->setPrefix(tr("nbColorsPerFlop="));
	sb_nbColorsAsked->setRange(1,25);
	sb_nbColorsAsked->setValue(4);
	
	showClassif=new QCheckBox("Display classification",win); 
	
	plotcolors=new PlotColors();
	
	le_question=new QLineEdit(win);
	
	gb_flops_params=new QGroupBox(tr("Flop Parameters"),win);
	
	te_results=new QTextEdit(win);
	
	layout=new QVBoxLayout(win);
	layout->addWidget(pb_loadFuzzyCLUT);
	
	QGridLayout * glayout=new QGridLayout();
	glayout->addWidget(sb_nbColorsAsked,0,0);
	glayout->addWidget(pb_askMe,1,0);
	glayout->addWidget(confiance_threshold,0,1);
	glayout->addWidget(similarity_threshold,0,2);
	glayout->addWidget(pbBarFlop,1,1);
	glayout->addWidget(showClassif,2,0);
	gb_flops_params->setLayout(glayout);
	
	layout->addWidget(gb_flops_params);
	layout->addWidget(le_question);
	layout->addWidget(plotcolors);
	QHBoxLayout * hlayout=new QHBoxLayout();
	hlayout->addWidget(pb_clear);
	hlayout->addWidget(pb_saveResults);
	layout->addLayout(hlayout);
	layout->addWidget(te_results);
	
	connect(pb_clear,SIGNAL(clicked()),this,SLOT(s_clearResults()));
	connect(pb_loadFuzzyCLUT,SIGNAL(clicked()),this,SLOT(s_loadFuzzyCLUT()));
	connect(pb_saveResults,SIGNAL(clicked()),this,SLOT(s_saveResults()));
	connect(pb_askMe,SIGNAL(clicked()),this,SLOT(s_askMe()));
	
	connect(showClassif,SIGNAL(stateChanged(int)),this,SLOT(s_showClassif(int)));
	
	results=tr("");
	
}
////////////////////////////////////////////////////////////////////////////////
void ModuleCLUTSurveyColorLimits::free()
{
	delete win;
}
////////////////////////////////////////////////////////////////////////////////
cv::Mat & ModuleCLUTSurveyColorLimits::process()
{

}
////////////////////////////////////////////////////////////////////////////////
void ModuleCLUTSurveyColorLimits::setInput(int n,const cv::Mat & m)
{
	
}
////////////////////////////////////////////////////////////////////////////////
QWidget* ModuleCLUTSurveyColorLimits::widget()
{
	return win;
}
////////////////////////////////////////////////////////////////////////////////
QString ModuleCLUTSurveyColorLimits::getName()
{
	return tr("Survey Type: Dual Colors Limit");
}
////////////////////////////////////////////////////////////////////////////////
int ModuleCLUTSurveyColorLimits::nbInputs()
{
	return 1;
}
////////////////////////////////////////////////////////////////////////////////
bool ModuleCLUTSurveyColorLimits::setParams(QString params)
{
	QStringList list_params=params.split(";");
		
	if(list_params.size()==3)
	{
		sb_nbColorsAsked->setValue(list_params[0].toInt());
		confiance_threshold->setValue(list_params[1].toInt());
		similarity_threshold->setValue(list_params[2].toInt());
		return true;
	}
	else
	{
		return false;
	}	
}
////////////////////////////////////////////////////////////////////////////////
QString ModuleCLUTSurveyColorLimits::getParams()
{
	return QString::number(sb_nbColorsAsked->value())+tr(";")+
		   QString::number(confiance_threshold->value())+tr(";")+
		   QString::number(similarity_threshold->value());
}

////////////////////////////////////////////////////////////////////////////////
QCVModuleInterface * ModuleCLUTSurveyColorLimits::clone()
{
	return new ModuleCLUTSurveyColorLimits;
}
////////////////////////////////////////////////////////////////////////////////
QString ModuleCLUTSurveyColorLimits::help(int id)
{
	if(id==-2)
	{
		return tr("This module provide an interface to make a survey in order to find the limit between chroatic and achromatic colors");
	}
	else if(id==-1)
	{
		return tr("image");
	}
	else if(id==0)
	{
		return tr("image");
	}
	else
	{
		return tr("erreur");
	}
}
////////////////////////////////////////////////////////////////////////////////
void ModuleCLUTSurveyColorLimits::s_loadFuzzyCLUT()
{
	QString fn=QFileDialog::getOpenFileName(win,"Charger une Fuzzy CLUT","data","*.txt");
	if(!fn.isEmpty())
	{
		if(loadFuzzyCLUT(fn,fuzzyclut))
		{
			maxFuzzyCLUT_2_CLUT(fuzzyclut,clut);
		}
	}
}
////////////////////////////////////////////////////////////////////////////////
void ModuleCLUTSurveyColorLimits::s_saveResults()
{
	QString fn=QFileDialog::getSaveFileName(win,"Charger une Fuzzy CLUT","data","*.txt");
	if(!fn.isEmpty())
	{
		QFile file(fn);
		if (file.open(QIODevice::WriteOnly | QIODevice::Text))
		{
			QTextStream out(&file);
			out << results;
			file.close();
		}
	}
}
////////////////////////////////////////////////////////////////////////////////
void ModuleCLUTSurveyColorLimits::s_askMe()
{
	plotcolors->update();
	srand(time(0));
	QString r = plotcolors->getResults();
	if(!r.isEmpty())
	{
		results+=r;
	}
	te_results->setText(results);
	
	if(!clut.empty())
	{
		//on efface le jeu de couleur precedent
		plotcolors->clearColors();
		
		//on choisi deux couleurs qui partagent une frontiere
		color1=rand()%11;
		cv::Mat_<float> adjenceMat;
		getConnexGraph(clut,fuzzyclut.cols,50,adjenceMat);
		do{color2=rand()%11;}while(adjenceMat(color1,color2)==0.0);
		plotcolors->setColors(color1,color2);
		
		le_question->setText(tr(" Which are ")+getC11Name(color2)+tr("?"));
		
		//on construit deux liste de couleur
		QList<QColor> strong_colors1;
		QList<QColor> strong_colors2;
		QList<QColor> weak_colors;
		
		float seuil=confiance_threshold->value()/100.0;
		float seuil2=similarity_threshold->value()/100.0;
		
		pbBarFlop->setRange(0,round(pow(fuzzyclut.rows,1.0/3.0)));
		int p=(int)256/round(pow(fuzzyclut.rows,1.0/3.0));
		
		for(int r=0;r<256;r+=p)
		{
			for(int g=0;g<256;g+=p)
			{
				for(int b=0;b<256;b+=p)
				{
					if( (FUZZY_CLUT(fuzzyclut,r,g,b,color1)>seuil))
					{
						strong_colors1+=QColor(r,g,b,CLUT(clut,r,g,b));
					}
					else if( (FUZZY_CLUT(fuzzyclut,r,g,b,color2)>seuil))
					{
						strong_colors2+=QColor(r,g,b,CLUT(clut,r,g,b));
					}
					else if( ((FUZZY_CLUT(fuzzyclut,r,g,b,color1)+FUZZY_CLUT(fuzzyclut,r,g,b,color2))>seuil) && 
							 (abs((FUZZY_CLUT(fuzzyclut,r,g,b,color1)-FUZZY_CLUT(fuzzyclut,r,g,b,color2)))<(seuil2)) )
					{
						weak_colors+=QColor(r,g,b,CLUT(clut,r,g,b));
					}
				}
			}
			pbBarFlop->setValue(r);
		}
		//on choisit i/2 couleurs dans la liste des non saturee 
		//on choisit i/2 couleurs dans la liste des saturee 
		
		if(strong_colors1.size()==0)
		{
			le_question->setText("The list of strong colors1 is empty");
			return;
		}
		if(strong_colors2.size()==0)
		{
			le_question->setText("The list of strong colors2 is empty");
			return;
		}
		if(weak_colors.size()==0)
		{
			le_question->setText("The list of weak colors is empty");
			return;
		}
		
		int index=0;
		
		QList<QColor> colors_final;
		
		for(int i=0;i<sb_nbColorsAsked->value();i++)
		{
			QColor color;
			if(i<sb_nbColorsAsked->value()/4)
			{
				index=rand()%strong_colors1.size();
				color=strong_colors1[index];
			}
			else if(i<sb_nbColorsAsked->value()/2)
			{
				index=rand()%strong_colors2.size();
				color=strong_colors2[index];
			}
			else
			{
				index=rand()%weak_colors.size();
				color=weak_colors[index];
			}
			
			colors_final+=color;
		}
		
		for(int i=0;i<sb_nbColorsAsked->value();i++)
		{
			qSwap(colors_final[rand()%colors_final.size()],colors_final[rand()%colors_final.size()]);
		}
		
		for(int i=0;i<sb_nbColorsAsked->value();i++)
		{
			plotcolors->addColors(colors_final[i]);
		}
	}
	else
	{
		le_question->setText(tr("Oups! I need a Fuzzy CLUT please..."));
	}
	parent->adjust();
}
void ModuleCLUTSurveyColorLimits::s_clearResults()
{
	results.clear();
	te_results->clear();
	te_results->setText(results);
}

void ModuleCLUTSurveyColorLimits::getBriSat(uchar r,uchar g,uchar b,uchar * L,uchar * S)
{
	uchar var_Min = std::min( std::min(r, g), b );    //Min. value of RGB
	uchar var_Max = std::max( std::max(r, g), b );    //Max. value of RGB
	uchar del_Max = var_Max - var_Min; 				//Delta RGB value

	*L = ( var_Max + var_Min ) / 2;

	if ( del_Max == 0 )                     //This is a gray, no chroma...
	{		                                //HSL results from 0 to 1
		*S = 0;
	}
	else                                    //Chromatic data...
	{
		if ( *L < 128 ) *S = (255 * del_Max) / ( var_Max + var_Min );
		else           *S = (255 * del_Max) / ( 512 - var_Max - var_Min );
	}
}

void ModuleCLUTSurveyColorLimits::s_showClassif(int display)
{
	plotcolors->displayClassif(display);
	plotcolors->update();
}
////////////////////////////////////////////////////////////////////////////////

Q_EXPORT_PLUGIN2(ModuleCLUTSurveyColorLimits_plugin,ModuleCLUTSurveyColorLimits);  